<template>
    <div ref="outer" class="scroll outer">
        <div ref="inner" :class="getInnerClass" :style="getInnerStyle">
            <slot />
        </div>
    </div>
</template>

<script lang="ts">
export default { name: 'Scroll' }
</script>

<script lang="ts" setup>
import { reactive, ref, computed, nextTick } from 'vue'

const emits = defineEmits(['scrollComplete'])

const props = defineProps({
    modelValue: {
        type: Array,
        default: () => []
    },
    direction: {
        type: String,
        validator(value:string) {
            return ['down', 'up'].includes(value)
        },
        default: 'down'
    },
    count: {
        type: Number,
        required: true
    },
    scrollDelay: {
        type: Number,
        default: 5000
    },
    updateDelay: {
        type: Number,
        default: 5000
    }
})

const getInnerClass = computed(() => {
    const cls = ['inner', `direction-${props.direction}-${stateEnum[state.state]}`]
    return cls.join(' ')
})

const innerHeight = () => {
    return inner.value?.offsetHeight || 0
}

const outerHeight = () => {
    return outer.value?.clientHeight || 0
}

const getInnerStyle = computed(() => {
    const style:any = {}

    const time = innerHeight() / 100
    if (state.state !== stateEnum.finish) style.transition = `${time}s`

    if (state.state === stateEnum.standBy) {
        const diff = outerHeight() - innerHeight()
        const height = diff > 0 ? diff : 0
        style.top = props.direction === 'up' ? `${height}px` : undefined
        style.bottom = props.direction === 'down' ? `${height}px` : undefined
    } else if (state.state === stateEnum.scrolling) {
        waitFinish(time)
        style.top = props.direction === 'up' ? `-${innerHeight() - outerHeight()}px` : undefined
        style.bottom = props.direction === 'down' ? `-${innerHeight() - outerHeight()}px` : undefined
    }
    return style
})

const waitFinish = (time:number) => {
    setTimeout(() => {
        state.state = stateEnum.finish
        if (props.direction === 'up') {
            // TODO 需取最后props.count条数据
        } else {
            // eslint-disable-next-line vue/no-mutating-props
            props.modelValue.splice(props.count)
        }

        setTimeout(() => {
            state.state = stateEnum.standBy
            emits('scrollComplete')
        }, props.updateDelay)
    }, time * 1000)
}

const outer = ref()
const inner = ref()

enum stateEnum {
    standBy,
    scrolling,
    finish
}

const state = reactive({
    state: stateEnum.finish
})

const startScroll = (list: any[]) => {
    // eslint-disable-next-line vue/no-mutating-props
    props.modelValue.splice(0, 0, ...list)
    nextTick(() => {
        state.state = stateEnum.standBy
        setTimeout(() => {
            state.state = stateEnum.scrolling
        }, props.scrollDelay)
    })
}

defineExpose({
    startScroll
})
</script>
<style lang="scss" scoped>
.scroll{
    position: relative;
    overflow: hidden;
    .inner{
        position: absolute;
        width: 100%;
        &.direction-down-standBy{
            bottom: 0;
        }
        &.direction-up-standBy{
            top: 0;
        }

        &.direction-down-scrolling{
            // bottom: 0;
        }
        &.direction-up-scrolling{
            // top: 0;
        }
    }
}
</style>
